<!DOCTYPE html>


  <html class="dark page-post">


<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="utf-8">
  
  <title>Ant Design Pro总结篇 | Poetry&#39;s Blog</title>

  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  
    <meta name="keywords" content="Dva,Umi,">
  

  <meta name="description" content="一、简介1.1 ant pro系统特性 基于 Ant Design 体系精心设计 使用 React/umi/dva/antd 等前端前沿技术开发 针对不同屏幕大小设计 可配置的主题满足多样化的品牌诉求 Mock 数据实用的本地数据调试方案  1.2 模板- Dashboard  - 分析页  - 监控页  - 工作台- 表单页  - 基础表单页  - 分步表单页  - 高级表单页- 列表页  -">
<meta name="keywords" content="Dva,Umi">
<meta property="og:type" content="article">
<meta property="og:title" content="Ant Design Pro总结篇">
<meta property="og:url" content="http://blog.poetries.top/2018/09/16/ant-design-pro/index.html">
<meta property="og:site_name" content="Poetry&#39;s Blog">
<meta property="og:description" content="一、简介1.1 ant pro系统特性 基于 Ant Design 体系精心设计 使用 React/umi/dva/antd 等前端前沿技术开发 针对不同屏幕大小设计 可配置的主题满足多样化的品牌诉求 Mock 数据实用的本地数据调试方案  1.2 模板- Dashboard  - 分析页  - 监控页  - 工作台- 表单页  - 基础表单页  - 分步表单页  - 高级表单页- 列表页  -">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://gw.alipayobjects.com/zos/rmsportal/oXmyfmffJVvdbmDoGvuF.png">
<meta property="og:image" content="https://gw.alipayobjects.com/zos/rmsportal/mXsydBXvLqBVEZLMssEy.png">
<meta property="og:image" content="https://gw.alipayobjects.com/zos/rmsportal/oXmyfmffJVvdbmDoGvuF.png">
<meta property="og:image" content="https://gw.alipayobjects.com/zos/rmsportal/mXsydBXvLqBVEZLMssEy.png">
<meta property="og:image" content="https://gw.alipayobjects.com/zos/rmsportal/hjDyFTVOgRwDzAIHApMO.png">
<meta property="og:image" content="https://gw.alipayobjects.com/zos/rmsportal/xZIqExWKhdnzDBjajnZg.png">
<meta property="og:image" content="https://gw.alipayobjects.com/zos/rmsportal/jJQYzRyqVFBBamUOppXH.png">
<meta property="og:image" content="https://gw.alipayobjects.com/zos/rmsportal/DbDSgiRukSANKWyhULir.png">
<meta property="og:updated_time" content="2020-08-15T04:25:31.902Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Ant Design Pro总结篇">
<meta name="twitter:description" content="一、简介1.1 ant pro系统特性 基于 Ant Design 体系精心设计 使用 React/umi/dva/antd 等前端前沿技术开发 针对不同屏幕大小设计 可配置的主题满足多样化的品牌诉求 Mock 数据实用的本地数据调试方案  1.2 模板- Dashboard  - 分析页  - 监控页  - 工作台- 表单页  - 基础表单页  - 分步表单页  - 高级表单页- 列表页  -">
<meta name="twitter:image" content="https://gw.alipayobjects.com/zos/rmsportal/oXmyfmffJVvdbmDoGvuF.png">

  

  
    <link rel="icon" href="/favicon.ico">
  

  <link href="/css/styles.css?v=c114cbeddx" rel="stylesheet">
<link href="/css/other.css?v=c114cbeddx" rel="stylesheet">


  
    <link rel="stylesheet" href="/css/personal-style.css">
  

  

  
  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "//hm.baidu.com/hm.js?40b1f89aa80f2527b3db779c6898c879";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>


  
  <script type="text/javascript">
	(function(){
	    var bp = document.createElement('script');
	    var curProtocol = window.location.protocol.split(':')[0];
	    if (curProtocol === 'https') {
	        bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';        
	    }
	    else {
	        bp.src = 'http://push.zhanzhang.baidu.com/push.js';
	    }
	    var s = document.getElementsByTagName("script")[0];
	    s.parentNode.insertBefore(bp, s);
	})();
  </script>



  
    <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <link rel="stylesheet" href="//cdn.bootcss.com/font-awesome/4.3.0/css/font-awesome.min.css">
  

  <!-- 聊天系统 -->
  
    
   <link type="text/css" rel="stylesheet" href="/renxi/default.css">
   <style>
      #modal {
        position: static !important;
      }
      .filter {
        width: 100%;
        height: 100%;
        position: absolute;
        top: 0;
        left: 0;
        background: #fe5757;
        animation: colorChange 30s ease-in-out infinite;
        animation-fill-mode: both;
        mix-blend-mode: overlay;
      }
  
      @keyframes colorChange {
        0%, 100% {
            opacity: 0;
        }
        50% {
            opacity: .9;
        }
      }
   </style>
</head>
</html>
<body>
  
  
    <span id="toolbox-mobile" class="toolbox-mobile">导航</span>
  

  <div class="post-header CENTER">
   
  <div class="toolbox">
    <a class="toolbox-entry" href="/">
      <span class="toolbox-entry-text">导航</span>
      <i class="icon-angle-down"></i>
      <i class="icon-home"></i>
    </a>
    <ul class="list-toolbox">
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/archives/"
            rel="noopener noreferrer"
            target="_self"
            >
            博客
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/categories/"
            rel="noopener noreferrer"
            target="_self"
            >
            分类
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/tags/"
            rel="noopener noreferrer"
            target="_self"
            >
            标签
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/search/"
            rel="noopener noreferrer"
            target="_self"
            >
            搜索
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/link/"
            rel="noopener noreferrer"
            target="_self"
            >
            友链
          </a>
        </li>
      
        <li class="item-toolbox">
          <a
            class="CIRCLE"
            href="/about/"
            rel="noopener noreferrer"
            target="_self"
            >
            关于
          </a>
        </li>
      
    </ul>
  </div>


</div>


  <div id="toc" class="toc-article">
    <strong class="toc-title">文章目录<i class="iconfont toc-title" style="display:inline-block;color:#87998d;width:20px;height:20px;">&#xf004b;</i></strong>
    <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#一、简介"><span class="toc-text">一、简介</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#1-1-ant-pro系统特性"><span class="toc-text">1.1 ant pro系统特性</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#1-2-模板"><span class="toc-text">1.2 模板</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#1-3-使用"><span class="toc-text">1.3 使用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#1-4-目录结构"><span class="toc-text">1.4 目录结构</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#roadhog摘要介绍"><span class="toc-text">roadhog摘要介绍</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#二、布局"><span class="toc-text">二、布局</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#2-1-Ant-Design-Pro-的布局"><span class="toc-text">2.1 Ant Design Pro 的布局</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-2-如何使用-Ant-Design-Pro-布局"><span class="toc-text">2.2 如何使用 Ant Design Pro 布局</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-3-Pro-扩展配置"><span class="toc-text">2.3 Pro 扩展配置</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2-4-Ant-Design-布局组件"><span class="toc-text">2.4 Ant Design 布局组件</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#四、路由和菜单"><span class="toc-text">四、路由和菜单</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#4-1-基本结构"><span class="toc-text">4.1 基本结构</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-1-1-路由"><span class="toc-text">4.1.1 路由</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-1-2-菜单"><span class="toc-text">4.1.2 菜单</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-1-3-面包屑"><span class="toc-text">4.1.3 面包屑</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#4-2-需求实例"><span class="toc-text">4.2 需求实例</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-1-新增页面"><span class="toc-text">4.2.1 新增页面</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-2-新增布局"><span class="toc-text">4.2.2 新增布局</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-2-3-带参数的路由"><span class="toc-text">4.2.3 带参数的路由</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#五、新增页面"><span class="toc-text">五、新增页面</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#5-1-新增-js、less"><span class="toc-text">5.1 新增 js、less</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-2-将文件加入菜单和路由"><span class="toc-text">5.2 将文件加入菜单和路由</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#5-3-新增-model、service"><span class="toc-text">5.3 新增 model、service</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#六、新增业务组件"><span class="toc-text">六、新增业务组件</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#七、样式"><span class="toc-text">七、样式</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#八、和服务端进行交互"><span class="toc-text">八、和服务端进行交互</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#九、引入外部模块"><span class="toc-text">九、引入外部模块</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#十、图表"><span class="toc-text">十、图表</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#十一、业务图标"><span class="toc-text">十一、业务图标</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#十二、Mock-和联调"><span class="toc-text">十二、Mock 和联调</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#十三、主题定制"><span class="toc-text">十三、主题定制</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#十四、权限管理"><span class="toc-text">十四、权限管理</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#权限组件-Authorized"><span class="toc-text">权限组件 Authorized</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#控制页面元素显示"><span class="toc-text">控制页面元素显示</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#demo关于权限简介"><span class="toc-text">demo关于权限简介</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#十五、构建和发布"><span class="toc-text">十五、构建和发布</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#十六、一些问题"><span class="toc-text">十六、一些问题</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#在ant-design-pro中解决跨域办法"><span class="toc-text">在ant-design-pro中解决跨域办法</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#在model中怎么同时发起多次请求"><span class="toc-text">在model中怎么同时发起多次请求</span></a></li></ol></li></ol>
  </div>
  




<div class="content content-post CENTER">
   <!-- canvas 彩带 -->
<canvas id="evanyou" width="1302" height="678" style="position: fixed;width: 100%;height: 100%;top: 0;left:0;z-index:-1;"></canvas>

<article id="post-ant-design-pro" class="article article-type-post" itemprop="blogPost">
  <header class="article-header" style="position:relative;">
    <h1 class="post-title">Ant Design Pro总结篇</h1>

    <div class="article-meta">
      <span>
        <i class="icon-calendar"></i>
        <span>2018.09.17</span>
      </span>

      
        <span class="article-author">
          <i class="icon-user"></i>
          <span>Poetry</span>
        </span>
      

      
  <span class="article-category">
    <i class="icon-list"></i>
    <a class="article-category-link" href="/categories/Front-End/">Front-End</a>
  </span>



      

      
      <i class="fa fa-eye"></i> 
        <span id="busuanzi_container_page_pv">
           &nbsp热度 <span id="busuanzi_value_page_pv">
           <i class="fa fa-spinner fa-spin"></i></span>℃
        </span>
      
      
       
          <span class="post-count">
            <i class="fa fa-file-word-o"></i>&nbsp
            <span>字数统计 7.7k字</span>
          </span>

          <span class="post-count">
            <i class="fa fa-columns"></i>&nbsp
            <span>阅读时长 32分</span>
          </span>
      
      
    </div>

    <i class="iconfont" id="toc-eye" style="display:inline-block;color:#b36619;position:absolute;top:0;right:0;cursor:pointer;
    font-size: 24px;">&#xe61c;</i>

  </header>

  <div class="article-content">
    
      <div id="container">
        <h1 id="一、简介"><a href="#一、简介" class="headerlink" title="一、简介"></a>一、简介</h1><h2 id="1-1-ant-pro系统特性"><a href="#1-1-ant-pro系统特性" class="headerlink" title="1.1 ant pro系统特性"></a>1.1 ant pro系统特性</h2><ul>
<li>基于 <code>Ant Design</code> 体系精心设计</li>
<li>使用 <code>React/umi/dva/antd</code> 等前端前沿技术开发</li>
<li>针对不同屏幕大小设计</li>
<li>可配置的主题满足多样化的品牌诉求</li>
<li><code>Mock</code> 数据实用的本地数据调试方案</li>
</ul>
<h2 id="1-2-模板"><a href="#1-2-模板" class="headerlink" title="1.2 模板"></a>1.2 模板</h2><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">- Dashboard</span><br><span class="line">  - 分析页</span><br><span class="line">  - 监控页</span><br><span class="line">  - 工作台</span><br><span class="line">- 表单页</span><br><span class="line">  - 基础表单页</span><br><span class="line">  - 分步表单页</span><br><span class="line">  - 高级表单页</span><br><span class="line">- 列表页</span><br><span class="line">  - 查询表格</span><br><span class="line">  - 标准列表</span><br><span class="line">  - 卡片列表</span><br><span class="line">  - 搜索列表（项目/应用/文章）</span><br><span class="line">- 详情页</span><br><span class="line">  - 基础详情页</span><br><span class="line">  - 高级详情页</span><br><span class="line">- 结果</span><br><span class="line">  - 成功页</span><br><span class="line">  - 失败页</span><br><span class="line">- 异常</span><br><span class="line">  - 403 无权限</span><br><span class="line">  - 404 找不到</span><br><span class="line">  - 500 服务器出错</span><br><span class="line">- 个人页</span><br><span class="line">  - 个人中心</span><br><span class="line">  - 个人设置</span><br><span class="line">- 帐户</span><br><span class="line">  - 登录</span><br><span class="line">  - 注册</span><br><span class="line">  - 注册成功</span><br></pre></td></tr></table></figure>
<h2 id="1-3-使用"><a href="#1-3-使用" class="headerlink" title="1.3 使用"></a>1.3 使用</h2><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ git clone --depth=1 https://github.com/ant-design/ant-design-pro.git my-project</span><br><span class="line">$ cd my-project</span><br></pre></td></tr></table></figure>
<p>或者</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ npm install ant-design-pro-cli -g</span><br><span class="line">$ mkdir my-project &amp;&amp; cd my-project</span><br><span class="line">$ pro new  # 安装脚手架</span><br></pre></td></tr></table></figure>
<h2 id="1-4-目录结构"><a href="#1-4-目录结构" class="headerlink" title="1.4 目录结构"></a>1.4 目录结构</h2><p>整个项目的目录结构</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">├── mock                     # 本地模拟数据</span><br><span class="line">├── node_modules             # 依赖库</span><br><span class="line">├── public</span><br><span class="line">│   ├── favicon.ico          # Favicon</span><br><span class="line">│   └── index.html           # HTML 入口模板</span><br><span class="line">├── src</span><br><span class="line">│   ├── common               # 应用公用配置，如导航信息</span><br><span class="line">│   ├── components           # 业务通用组件</span><br><span class="line">│   ├── e2e                  # 集成测试用例</span><br><span class="line">│   ├── layouts              # 通用布局</span><br><span class="line">│   ├── models               # dva model</span><br><span class="line">│   ├── routes               # 业务页面入口和常用模板</span><br><span class="line">│   ├── services             # 后台接口服务</span><br><span class="line">│   ├── utils                # 工具库</span><br><span class="line">│   ├── g2.js                # 可视化图形配置</span><br><span class="line">│   ├── polyfill.js          # 兼容性垫片</span><br><span class="line">│   ├── theme.js             # 主题配置</span><br><span class="line">│   ├── index.js             # 应用入口</span><br><span class="line">│   ├── index.less           # 全局样式</span><br><span class="line">│   └── router.js            # 路由入口</span><br><span class="line">├── tests                    # 测试工具</span><br><span class="line">├── .editorconfig            # 编辑器配置</span><br><span class="line">├── .eslintrc                # js代码检测工具</span><br><span class="line">├── .ga                      # 未知</span><br><span class="line">├── .gitignore               # git版本配置</span><br><span class="line">├── .roadhogrc               # roadhog配置</span><br><span class="line">├── .roadhogrc.mock.js       # roadhog的模拟配置</span><br><span class="line">├── .stylelintrc             # css代码审查配置</span><br><span class="line">├── .travis.yml              # travis持续构建工具配置</span><br><span class="line">├── package.json             # web前端项目配置文件</span><br><span class="line">├── README.md</span><br><span class="line">└──</span><br></pre></td></tr></table></figure>
<h2 id="roadhog摘要介绍"><a href="#roadhog摘要介绍" class="headerlink" title="roadhog摘要介绍"></a>roadhog摘要介绍</h2><ul>
<li><code>roadhog</code> 是一个 <code>cli</code> 工具，提供 <code>server</code>、 <code>build</code> 和 test 三个命令，分别用于本地调试和构建，并且提供了特别易用的 mock 功能。命令行体验和 <code>create-react-app</code> 一致，配置略有不同，比如默认开启 <code>css</code> <code>modules</code>，然后还提供了 <code>JSON</code> 格式的配置方式。</li>
<li>重点介绍<code>roadhog</code>有关的几个配置项，主要是在<code>ant design pro</code>的代码中用到了这些配置项</li>
</ul>
<p><strong>entry</strong></p>
<ul>
<li>指定 <code>webpack</code> 入口文件，支持 <code>glob</code>格式。</li>
<li>如果你的项目是多页类型，会希望把 <code>src/pages</code>的文件作为入口。可以这样配：</li>
</ul>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">&quot;entry&quot;: &quot;src/pages/\*.js&quot;</span><br></pre></td></tr></table></figure>
<p><strong>env</strong></p>
<blockquote>
<p>针对特定的环境进行配置。<code>server</code> 的环境变量是 <code>development</code>，<code>build</code> 的环境变量是<code>production</code>。</p>
</blockquote>
<p>比如：</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="string">"extraBabelPlugins"</span>: [<span class="string">"transform-runtime"</span>],</span><br><span class="line"><span class="string">"env"</span>: &#123;</span><br><span class="line">  <span class="string">"development"</span>: &#123;</span><br><span class="line">    <span class="string">"extraBabelPlugins"</span>: [<span class="string">"dva-hmr"</span>]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>这样，开发环境下的 <code>extraBabelPlugins</code> 是 <code>[&quot;transform-runtime&quot;, &quot;dva-hmr&quot;]</code>，而生产环境下是 <code>[&quot;transform-runtime&quot;]</code>。</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="string">"env"</span>: &#123;</span><br><span class="line">  <span class="string">"development"</span>: &#123;</span><br><span class="line">    <span class="string">"extraBabelPlugins"</span>: [</span><br><span class="line">      <span class="string">"dva-hmr"</span>,</span><br><span class="line">      <span class="string">"transform-runtime"</span>,</span><br><span class="line">      <span class="string">"transform-decorators-legacy"</span>,</span><br><span class="line">      <span class="string">"transform-class-properties"</span>,</span><br><span class="line">      [<span class="string">"import"</span>, &#123; <span class="string">"libraryName"</span>: <span class="string">"antd"</span>, <span class="string">"style"</span>: <span class="literal">true</span> &#125;]</span><br><span class="line">    ]</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">"production"</span>: &#123;</span><br><span class="line">    <span class="string">"extraBabelPlugins"</span>: [</span><br><span class="line">      <span class="string">"transform-runtime"</span>,</span><br><span class="line">      <span class="string">"transform-decorators-legacy"</span>,</span><br><span class="line">      <span class="string">"transform-class-properties"</span>,</span><br><span class="line">      [<span class="string">"import"</span>, &#123; <span class="string">"libraryName"</span>: <span class="string">"antd"</span>, <span class="string">"style"</span>: <span class="literal">true</span> &#125;]</span><br><span class="line">    ]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>在这段代码中，开发环境和生产环境分别配置，其中开发环境使用了<code>dva-hmr</code>插件</p>
</blockquote>
<h1 id="二、布局"><a href="#二、布局" class="headerlink" title="二、布局"></a>二、布局</h1><blockquote>
<p>页面整体布局是一个产品最外层的框架结构，往往会包含导航、页脚、侧边栏、通知栏以及内容等。在页面之中，也有很多区块的布局结构。在真实项目中，页面布局通常统领整个应用的界面，有非常重要的作用</p>
</blockquote>
<h2 id="2-1-Ant-Design-Pro-的布局"><a href="#2-1-Ant-Design-Pro-的布局" class="headerlink" title="2.1 Ant Design Pro 的布局"></a>2.1 Ant Design Pro 的布局</h2><blockquote>
<p>在 Ant Design Pro 中，我们抽离了使用过程中的通用布局，都放在 <code>layouts</code> 目录中，分别为</p>
</blockquote>
<p><strong>BasicLayout：基础页面布局，包含了头部导航，侧边栏和通知栏</strong></p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/oXmyfmffJVvdbmDoGvuF.png" alt></p>
<p><strong>UserLayout：抽离出用于登陆注册页面的通用布局</strong></p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/mXsydBXvLqBVEZLMssEy.png" alt></p>
<p><strong>BlankLayout：空白的布局</strong></p>
<h2 id="2-2-如何使用-Ant-Design-Pro-布局"><a href="#2-2-如何使用-Ant-Design-Pro-布局" class="headerlink" title="2.2 如何使用 Ant Design Pro 布局"></a>2.2 如何使用 Ant Design Pro 布局</h2><blockquote>
<p>通常布局是和路由系统紧密结合的，Ant Design Pro 的路由使用了 <code>Umi</code> 的路由方案，为了统一方便的管理路由和页面的关系，我们将配置信息统一抽离到 <code>config/router.config.js</code> 下，通过如下配置定义每个页面的布局</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = [&#123;</span><br><span class="line">  path: <span class="string">'/'</span>,</span><br><span class="line">  component: <span class="string">'../layouts/BasicLayout'</span>,  <span class="comment">// 指定以下页面的布局</span></span><br><span class="line">  routes: [</span><br><span class="line">    <span class="comment">// dashboard</span></span><br><span class="line">    &#123; <span class="attr">path</span>: <span class="string">'/'</span>, <span class="attr">redirect</span>: <span class="string">'/dashboard/analysis'</span> &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      path: <span class="string">'/dashboard'</span>,</span><br><span class="line">      name: <span class="string">'dashboard'</span>,</span><br><span class="line">      icon: <span class="string">'dashboard'</span>,</span><br><span class="line">      routes: [</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">'/dashboard/analysis'</span>, <span class="attr">name</span>: <span class="string">'analysis'</span>, <span class="attr">component</span>: <span class="string">'./Dashboard/Analysis'</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">'/dashboard/monitor'</span>, <span class="attr">name</span>: <span class="string">'monitor'</span>, <span class="attr">component</span>: <span class="string">'./Dashboard/Monitor'</span> &#125;,</span><br><span class="line">        &#123; <span class="attr">path</span>: <span class="string">'/dashboard/workplace'</span>, <span class="attr">name</span>: <span class="string">'workplace'</span>, <span class="attr">component</span>: <span class="string">'./Dashboard/Workplace'</span> &#125;,</span><br><span class="line">      ],</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">&#125;]</span><br></pre></td></tr></table></figure>
<blockquote>
<p>更多 Umi 的路由配置方式可以参考：<a href="https://umijs.org/guide/router.html#%E9%85%8D%E7%BD%AE%E5%BC%8F%E8%B7%AF%E7%94%B1" target="_blank" rel="noopener">Umi 配置式路由</a></p>
</blockquote>
<h2 id="2-3-Pro-扩展配置"><a href="#2-3-Pro-扩展配置" class="headerlink" title="2.3 Pro 扩展配置"></a>2.3 Pro 扩展配置</h2><blockquote>
<p>我们在 <code>router.config.js</code> 扩展了一些关于 <code>pro</code> 全局菜单的配置</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  name: <span class="string">'dashboard'</span>,</span><br><span class="line">  icon: <span class="string">'dashboard'</span>,</span><br><span class="line">  hideInMenu: <span class="literal">true</span>,</span><br><span class="line">  hideChildrenInMenu: <span class="literal">true</span>,</span><br><span class="line">  hideInBreadcrumb: <span class="literal">true</span>,</span><br><span class="line">  authority: [<span class="string">'admin'</span>],</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li><code>name</code>: 当前路由在菜单和面包屑中的名称，注意这里是国际化配置的 <code>key</code>，具体展示菜单名可以在 <code>/src/locales/zh-CN.js</code> 进行配置。</li>
<li><code>icon</code>: 当前路由在菜单下的图标名。</li>
<li><code>hideInMenu</code>: 当前路由在菜单中不展现，默认 <code>false</code>。</li>
<li><code>hideChildrenInMenu</code>: 当前路由的子级在菜单中不展现，默认 <code>false</code>。</li>
<li><code>hideInBreadcrumb</code>: 当前路由在面包屑中不展现，默认 <code>false</code>。</li>
<li><code>authority</code>: 允许展示的权限，不设则都可见，详见：权限管理</li>
</ul>
<h2 id="2-4-Ant-Design-布局组件"><a href="#2-4-Ant-Design-布局组件" class="headerlink" title="2.4 Ant Design 布局组件"></a>2.4 Ant Design 布局组件</h2><blockquote>
<p>除了 Pro 里的内建布局以为，在一些页面中需要进行布局，可以使用 Ant Design 目前提供的两套布局组件工具：<code>Layout</code> 和 <code>Grid</code></p>
</blockquote>
<p><strong>Grid 组件</strong></p>
<blockquote>
<ul>
<li>栅格布局是网页中最常用的布局，其特点就是按照一定比例划分页面，能够随着屏幕的变化依旧保持比例，从而具有弹性布局的特点。</li>
<li>而 Ant Design 的栅格组件提供的功能更为强大，能够设置间距、具有支持响应式的比例设置，以及支持 flex 模式，基本上涵盖了大部分的布局场景 <a href="https://ant.design/components/grid/" target="_blank" rel="noopener">https://ant.design/components/grid/</a></li>
</ul>
</blockquote>
<p><strong>Layout 组件</strong></p>
<blockquote>
<p>如果你需要辅助页面框架级别的布局设计，那么 Layout 则是你最佳的选择，它抽象了大部分框架布局结构，使得只需要填空就可以开发规范专业的页面整体布局 <a href="https://ant.design/components/layout-cn/" target="_blank" rel="noopener">https://ant.design/components/layout-cn/</a></p>
</blockquote>
<ul>
<li>根据不同场景区分抽离布局组件#<br>在大部分场景下，我们需要基于上面两个组件封装一些适用于当下具体业务的组件，包含了通用的导航、侧边栏、顶部通知、页面标题等元素。例如 Ant Design Pro 的 <code>BasicLayout</code>。</li>
<li>通常，我们会把抽象出来的布局组件，放到跟 pages、 components 平行的 layouts 文件夹中方便管理。需要注意的是，这些布局组件和我们平时使用的其它组件并没有什么不同，只不过功能性上是为了处理布局问题</li>
</ul>
<h1 id="四、路由和菜单"><a href="#四、路由和菜单" class="headerlink" title="四、路由和菜单"></a>四、路由和菜单</h1><blockquote>
<p>路由和菜单是组织起一个应用的关键骨架，pro 中的路由为了方便管理，使用了中心化的方式，在 <code>router.config.js</code> 统一配置和管理</p>
</blockquote>
<h2 id="4-1-基本结构"><a href="#4-1-基本结构" class="headerlink" title="4.1 基本结构"></a>4.1 基本结构</h2><ul>
<li><strong>路由管理</strong> 通过约定的语法根据在 <code>router.config.js</code> 中配置路由。</li>
<li><strong>菜单生成</strong> 根据路由配置来生成菜单。菜单项名称，嵌套路径与路由高度耦合。</li>
<li><strong>面包屑</strong> 组件 <a href="https://pro.ant.design/components/PageHeader-cn" target="_blank" rel="noopener">PageHeader</a> 中内置的面包屑也可由脚手架提供的配置信息自动生成</li>
</ul>
<h3 id="4-1-1-路由"><a href="#4-1-1-路由" class="headerlink" title="4.1.1 路由"></a>4.1.1 路由</h3><blockquote>
<p>目前脚手架中所有的路由都通过 <code>router.config.js</code> 来统一管理，在 <code>umi</code> 的配置中我们增加了一些参数，如<code>name</code>,<code>icon</code>,<code>hideChildren</code>,<code>authority</code>，来辅助生成菜单。其中</p>
</blockquote>
<ul>
<li><code>name</code> 和 <code>icon</code>分别代表生成菜单项的图标和文本。</li>
<li><code>hideChildren</code> 用于隐藏不需要在菜单中展示的子路由。用法可以查看 分步表单 的配置。</li>
<li><code>hideInMenu</code> 可以在菜单中不展示这个路由，包括子路由。效果可以查看 <code>exception/trigger</code>页面。</li>
<li><code>authority</code> 用来配置这个路由的权限，如果配置了将会验证当前用户的权限，并决定是否展示</li>
</ul>
<h3 id="4-1-2-菜单"><a href="#4-1-2-菜单" class="headerlink" title="4.1.2 菜单"></a>4.1.2 菜单</h3><blockquote>
<p>菜单根据 <code>router.config.js</code> 生成，具体逻辑在 <code>src/layouts/BasicLayout</code> 中的 <code>formatter</code> 方法实现</p>
</blockquote>
<ul>
<li>如果你的项目并不需要菜单，你可以直接在<code>BasicLayout</code> 中删除 <code>SiderMenu</code> 组件的挂载。并在 <code>src/layouts/BasicLayout</code> 中 设置 <code>const MenuData = []</code>。</li>
<li>如果你需要从服务器请求菜单，可以将<code>menuData</code>设置为 <code>state</code>，然后通过网络获取来修改了 <code>state</code></li>
</ul>
<h3 id="4-1-3-面包屑"><a href="#4-1-3-面包屑" class="headerlink" title="4.1.3 面包屑"></a>4.1.3 面包屑</h3><blockquote>
<p>面包屑由 <code>PageHeaderLayout</code> 实现，<code>MenuContext</code> 将 根据 <code>MenuData</code> 生成的 <code>breadcrumbNameMap</code> 通过<code>props</code> 传递给了 <code>PageHeader</code>，如果你要做自定义的面包屑，可以通过修改传入的 <code>breadcrumbNameMap</code> 来解决</p>
</blockquote>
<p><code>breadcrumbNameMap</code> 示例数据如下：</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">'/'</span>: &#123; <span class="attr">path</span>: <span class="string">'/'</span>, <span class="attr">redirect</span>: <span class="string">'/dashboard/analysis'</span>, <span class="attr">locale</span>: <span class="string">'menu'</span> &#125;,</span><br><span class="line">  <span class="string">'/dashboard/analysis'</span>: &#123;</span><br><span class="line">    name: <span class="string">'analysis'</span>,</span><br><span class="line">    component: <span class="string">'./Dashboard/Analysis'</span>,</span><br><span class="line">    locale: <span class="string">'menu.dashboard.analysis'</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">  ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="4-2-需求实例"><a href="#4-2-需求实例" class="headerlink" title="4.2 需求实例"></a>4.2 需求实例</h2><h3 id="4-2-1-新增页面"><a href="#4-2-1-新增页面" class="headerlink" title="4.2.1 新增页面"></a>4.2.1 新增页面</h3><blockquote>
<p>脚手架默认提供了两种布局模板：基础布局 - <code>BasicLayout</code> 以及 账户相关布局 - <code>UserLayout</code></p>
</blockquote>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/oXmyfmffJVvdbmDoGvuF.png" alt></p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/mXsydBXvLqBVEZLMssEy.png" alt></p>
<p>如果你的页面可以利用这两种布局，那么只需要在路由配置中增加一条即可</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"> <span class="comment">// app</span></span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">'/'</span>,</span><br><span class="line">    component: <span class="string">'../layouts/BasicLayout'</span>,</span><br><span class="line">    routes: [</span><br><span class="line">      <span class="comment">// dashboard</span></span><br><span class="line">      &#123; <span class="attr">path</span>: <span class="string">'/'</span>, <span class="attr">redirect</span>: <span class="string">'/dashboard/analysis'</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">path</span> :<span class="string">'/dashboard/test'</span>,<span class="attr">component</span>:<span class="string">"./Dashboard/Test"</span>&#125;,</span><br><span class="line">    ...</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>
<blockquote>
<p>加好后，会默认生成相关的路由及导航</p>
</blockquote>
<h3 id="4-2-2-新增布局"><a href="#4-2-2-新增布局" class="headerlink" title="4.2.2 新增布局"></a>4.2.2 新增布局</h3><blockquote>
<p>在脚手架中我们通过嵌套路由来实现布局模板。<code>router.config.js</code> 是一个数组，其中第一级数据就是我们的布局，如果你需要新增布局可以在直接增加一个新的一级数组</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = [</span><br><span class="line">   <span class="comment">// user</span></span><br><span class="line">   &#123;</span><br><span class="line">    path: <span class="string">'/user'</span>,</span><br><span class="line">    component: <span class="string">'../layouts/UserLayout'</span>,</span><br><span class="line">    routes:[...]</span><br><span class="line">   &#125;,</span><br><span class="line">   <span class="comment">// app</span></span><br><span class="line">   &#123;</span><br><span class="line">    path: <span class="string">'/'</span>,</span><br><span class="line">    component: <span class="string">'../layouts/BasicLayout'</span>,</span><br><span class="line">    routes:[...]</span><br><span class="line">   &#125;,</span><br><span class="line">   <span class="comment">// new</span></span><br><span class="line">   &#123;</span><br><span class="line">    path: <span class="string">'/new'</span>,</span><br><span class="line">    component: <span class="string">'../layouts/new_page'</span>,</span><br><span class="line">    routes:[...]</span><br><span class="line">   &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure>
<h3 id="4-2-3-带参数的路由"><a href="#4-2-3-带参数的路由" class="headerlink" title="4.2.3 带参数的路由"></a>4.2.3 带参数的路由</h3><blockquote>
<p>脚手架默认支持带参数的路由,但是在菜单中显示带参数的路由并不是个好主意，我们并不会自动的帮你注入一个参数，你可能需要在代码中自行处理</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">&#123; </span><br><span class="line">    path: <span class="string">'/dashboard/:page'</span>,</span><br><span class="line">    hideInMenu:<span class="literal">true</span>, </span><br><span class="line">    name: <span class="string">'analysis'</span>, </span><br><span class="line">    component: <span class="string">'./Dashboard/Analysis'</span> </span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>
<p>你可以通过以下代码来跳转到这个路由</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">'umi/router'</span>;</span><br><span class="line"></span><br><span class="line">router.push(<span class="string">'/dashboard/anyParams'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">//or</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> Link <span class="keyword">from</span> <span class="string">'umi/link'</span>;</span><br><span class="line"></span><br><span class="line">&lt;Link to=<span class="string">"/dashboard/anyParams"</span>&gt;go&lt;<span class="regexp">/Link&gt;</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>在路由组件中，可以通过<code>this.props.match.params</code> 来获得路由参数</p>
</blockquote>
<h1 id="五、新增页面"><a href="#五、新增页面" class="headerlink" title="五、新增页面"></a>五、新增页面</h1><blockquote>
<p>这里的『页面』指配置了路由，能够通过链接直接访问的模块，要新建一个页面，通常只需要在脚手架的基础上进行简单的配置</p>
</blockquote>
<h2 id="5-1-新增-js、less"><a href="#5-1-新增-js、less" class="headerlink" title="5.1 新增 js、less"></a>5.1 新增 js、less</h2><blockquote>
<p>在 <code>src/pages</code> 下新建页面的 <code>js</code> 及 <code>less</code> 文件，如果相关页面有多个，可以新建一个文件夹来放置相关文件</p>
</blockquote>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/hjDyFTVOgRwDzAIHApMO.png" alt></p>
<blockquote>
<p>样式文件默认使用 CSS Modules，如果需要，你可以在样式文件的头部引入 antd 样式变量文件</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">@import &quot;~antd/lib/style/themes/default.less&quot;;</span><br></pre></td></tr></table></figure>
<h2 id="5-2-将文件加入菜单和路由"><a href="#5-2-将文件加入菜单和路由" class="headerlink" title="5.2 将文件加入菜单和路由"></a>5.2 将文件加入菜单和路由</h2><blockquote>
<p>加入菜单和路由的方式请参照 路由和菜单 - 添加路由/菜单 中的介绍完成。加好后，访问 <code>http://localhost:8000/#/new</code> 就可以看到新增的页面了 <a href="https://pro.ant.design/docs/router-and-nav-cn#%E6%B7%BB%E5%8A%A0%E8%B7%AF%E7%94%B1/%E8%8F%9C%E5%8D%95" target="_blank" rel="noopener">https://pro.ant.design/docs/router-and-nav-cn#%E6%B7%BB%E5%8A%A0%E8%B7%AF%E7%94%B1/%E8%8F%9C%E5%8D%95</a></p>
</blockquote>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/xZIqExWKhdnzDBjajnZg.png" alt></p>
<h2 id="5-3-新增-model、service"><a href="#5-3-新增-model、service" class="headerlink" title="5.3 新增 model、service"></a>5.3 新增 model、service</h2><blockquote>
<p>布局及路由都配置好之后，回到之前新建的 <code>NewPage.js</code>，可以开始写业务代码了！如果需要用到 <code>dva</code> 中的数据流，还需要在 <code>src/models src/services</code> 中建立相应的<code>model</code> 和 service，具体可以参考脚手架内置页面的写法</p>
</blockquote>
<h1 id="六、新增业务组件"><a href="#六、新增业务组件" class="headerlink" title="六、新增业务组件"></a>六、新增业务组件</h1><blockquote>
<p>对于一些可能被多处引用的功能模块，建议提炼成业务组件统一管理。这些组件一般有以下特征：</p>
</blockquote>
<ul>
<li>只负责一块相对独立，稳定的功能；</li>
<li>没有单独的路由配置；</li>
<li>可能是纯静态的，也可能包含自己的 state，但不涉及 dva 的数据流，仅受父组件（通常是一个页面）传递的参数控制。</li>
</ul>
<p><strong>新建文件</strong></p>
<blockquote>
<p>在 <code>src/components</code> 下新建一个以组件名命名的文件夹，注意首字母大写，命名尽量体现组件的功能，这里就叫 <code>ImageWrapper</code>。在此文件夹下新增 js 文件及样式文件（如果需要），命名为 <code>index.js</code>和 <code>index.less</code></p>
</blockquote>
<ul>
<li>在使用组件时，默认会在 <code>index.js</code> 中寻找 <code>export</code> 的对象，如果你的组件比较复杂，可以分为多个文件，最后在 <code>index.js</code>中统一 <code>export</code>，就像这样</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// MainComponent.js</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> (&#123; ... &#125;) =&gt; (...);</span><br><span class="line"></span><br><span class="line"><span class="comment">// SubComponent1.js</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> (&#123; ... &#125;) =&gt; (...);</span><br><span class="line"></span><br><span class="line"><span class="comment">// SubComponent2.js</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> (&#123; ... &#125;) =&gt; (...);</span><br><span class="line"></span><br><span class="line"><span class="comment">// index.js</span></span><br><span class="line"><span class="keyword">import</span> MainComponent <span class="keyword">from</span> <span class="string">'./MainComponent'</span>;</span><br><span class="line"><span class="keyword">import</span> SubComponent1 <span class="keyword">from</span> <span class="string">'./SubComponent1'</span>;</span><br><span class="line"><span class="keyword">import</span> SubComponent2 <span class="keyword">from</span> <span class="string">'./SubComponent2'</span>;</span><br><span class="line"></span><br><span class="line">MainComponent.SubComponent1 = SubComponent1;</span><br><span class="line">MainComponent.SubComponent2 = SubComponent2;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> MainComponent;</span><br></pre></td></tr></table></figure>
<p>你的代码大概是这个样子</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// index.js</span></span><br><span class="line"><span class="keyword">import</span> React <span class="keyword">from</span> <span class="string">'react'</span>;</span><br><span class="line"><span class="keyword">import</span> styles <span class="keyword">from</span> <span class="string">'./index.less'</span>;    <span class="comment">// 按照 CSS Modules 的方式引入样式文件。</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> (&#123; src, desc, style &#125;) =&gt; (</span><br><span class="line">  &lt;div style=&#123;style&#125; className=&#123;styles.imageWrapper&#125;&gt;</span><br><span class="line">    &lt;img className=&#123;styles.img&#125; src=&#123;src&#125; alt=&#123;desc&#125; /&gt;</span><br><span class="line">    &#123;desc &amp;&amp; <span class="xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">className</span>=<span class="string">&#123;styles.desc&#125;</span>&gt;</span>&#123;desc&#125;<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span>&#125;</span><br><span class="line">  &lt;<span class="regexp">/div&gt;</span></span><br><span class="line"><span class="regexp">);</span></span><br></pre></td></tr></table></figure>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line">// index.less</span><br><span class="line"><span class="selector-class">.imageWrapper</span> &#123;</span><br><span class="line">  <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">20px</span> <span class="number">8px</span>;</span><br><span class="line">  <span class="attribute">background</span>: <span class="number">#f2f4f5</span>;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">400px</span>;</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">0</span> auto;</span><br><span class="line">  <span class="attribute">text-align</span>: center;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.img</span> &#123;</span><br><span class="line">  <span class="attribute">vertical-align</span>: middle;</span><br><span class="line">  <span class="attribute">max-width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">32px</span>);</span><br><span class="line">  <span class="attribute">margin</span>: <span class="number">2.4em</span> <span class="number">1em</span>;</span><br><span class="line">  <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">8px</span> <span class="number">20px</span> <span class="built_in">rgba</span>(<span class="number">143</span>, <span class="number">168</span>, <span class="number">191</span>, <span class="number">0.35</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>使用</strong></p>
<blockquote>
<p>在要使用这个组件的地方，按照组件定义的 <code>API</code> 传入参数，直接使用就好，不过别忘了先引入</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> React <span class="keyword">from</span> <span class="string">'react'</span>;</span><br><span class="line"><span class="keyword">import</span> ImageWrapper <span class="keyword">from</span> <span class="string">'@/components/ImageWrapper'</span>;  <span class="comment">// @ 表示相对于源文件根目录</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> () =&gt; (</span><br><span class="line">  &lt;ImageWrapper</span><br><span class="line">    src=<span class="string">"https://os.alipayobjects.com/rmsportal/mgesTPFxodmIwpi.png"</span></span><br><span class="line">    desc=<span class="string">"示意图"</span></span><br><span class="line">  /&gt;</span><br><span class="line">);</span><br></pre></td></tr></table></figure>
<h1 id="七、样式"><a href="#七、样式" class="headerlink" title="七、样式"></a>七、样式</h1><p><strong>less</strong></p>
<blockquote>
<p>Ant Design Pro 默认使用 less 作为样式语言</p>
</blockquote>
<p><strong>CSS Modules</strong></p>
<p>在样式开发过程中，有两个问题比较突出</p>
<ul>
<li>全局污染 —— CSS 文件中的选择器是全局生效的，不同文件中的同名选择器，根据 build 后生成文件中的先后顺序，后面的样式会将前面的覆盖；</li>
<li>选择器复杂 —— 为了避免上面的问题，我们在编写样式的时候不得不小心翼翼，类名里会带上限制范围的标识，变得越来越长，多人开发时还很容易导致命名风格混乱，一个元素上使用的选择器个数也可能越来越多。</li>
</ul>
<blockquote>
<p>为了解决上述问题，我们的脚手架默认使用 CSS Modules 模块化方案，先来看下在这种模式下怎么写样式</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">// example.js</span><br><span class="line">import styles from &apos;./example.less&apos;;</span><br><span class="line"></span><br><span class="line">export default (&#123; title &#125;) =&gt; &lt;div className=&#123;styles.title&#125;&gt;&#123;title&#125;&lt;/div&gt;;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">// example.less</span><br><span class="line">.title &#123;</span><br><span class="line">  color: @heading-color;</span><br><span class="line">  font-weight: 600;</span><br><span class="line">  margin-bottom: 16px;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>用 less 写样式好像没什么改变，只是类名比较简单（实际项目中也是这样），js 文件的改变就是在设置 <code>className</code> 时，用一个对象属性取代了原来的字符串，属性名跟 less 文件中对应的类名相同，对象从 less 文件中引入。</li>
<li>在上面的样式文件中，<code>.title</code> 只会在本文件生效，你可以在其他任意文件中使用同名选择器，也不会对这里造成影响。不过有的时候，我们就是想要一个全局生效的样式呢？可以使用 <code>:global</code></li>
</ul>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">// example.less</span><br><span class="line">.title &#123;</span><br><span class="line">  color: @heading-color;</span><br><span class="line">  font-weight: 600;</span><br><span class="line">  margin-bottom: 16px;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 定义全局样式 */</span><br><span class="line">:global(.text) &#123;</span><br><span class="line">  font-size: 16px;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 定义多个全局样式 */</span><br><span class="line">:global &#123;</span><br><span class="line">  .footer &#123;</span><br><span class="line">    color: #ccc;</span><br><span class="line">  &#125;</span><br><span class="line">  .sider &#123;</span><br><span class="line">    background: #ebebeb;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>CSS Modules 的基本原理很简单，就是对每个类名（非 <code>:global</code> 声明的）按照一定规则进行转换，保证它的唯一性。如果在浏览器里查看这个示例的 dom 结构，你会发现实际渲染出来是这样的</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">&lt;div class=&quot;title___3TqAx&quot;&gt;title&lt;/div&gt;</span><br></pre></td></tr></table></figure>
<ul>
<li>类名被自动添加了一个 <code>hash</code> 值，这保证了它的唯一性</li>
</ul>
<p><strong>样式文件类别</strong></p>
<blockquote>
<p>在一个项目中，样式文件根据功能不同，可以划分为不同的类别</p>
</blockquote>
<ul>
<li><code>src/index.less#</code></li>
</ul>
<blockquote>
<p>全局样式文件，在这里你可以进行一些通用设置，比如脚手架中自带的</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">html, body, :global(#root) &#123;</span><br><span class="line">  height: 100%;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">body &#123;</span><br><span class="line">  text-rendering: optimizeLegibility;</span><br><span class="line">  -webkit-font-smoothing: antialiased;</span><br><span class="line">  -moz-osx-font-smoothing: grayscale;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// temporary font size patch</span><br><span class="line">:global(.ant-tag) &#123;</span><br><span class="line">  font-size: 12px;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<ul>
<li><code>src/utils/utils.less#</code></li>
</ul>
<blockquote>
<p>这里可以放置一些工具函数供调用，比如清除浮动 <code>.clearfix</code></p>
</blockquote>
<ul>
<li>模块样式</li>
</ul>
<blockquote>
<p>针对某个模块/页面生效的文件</p>
</blockquote>
<h1 id="八、和服务端进行交互"><a href="#八、和服务端进行交互" class="headerlink" title="八、和服务端进行交互"></a>八、和服务端进行交互</h1><p><strong>前端请求流程</strong></p>
<blockquote>
<p>在 Ant Design Pro 中，一个完整的前端 UI 交互到服务端处理流程是这样的</p>
</blockquote>
<ul>
<li>UI 组件交互操作；</li>
<li>调用 <code>model</code> 的 <code>effect</code>；</li>
<li>调用统一管理的 <code>service</code> 请求函数；</li>
<li>使用封装的 <code>request.js</code>发送请求；</li>
<li>获取服务端返回；</li>
<li>然后调用<code>reducer</code>改变 <code>state</code>；</li>
<li>更新 <code>model</code></li>
</ul>
<blockquote>
<p>为了方便管理维护，统一的请求处理都放在 services 文件夹中，并且一般按照 model 维度进行拆分文件</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">services/</span><br><span class="line">  user.js</span><br><span class="line">  api.js</span><br><span class="line">  ...</span><br></pre></td></tr></table></figure>
<blockquote>
<p>其中，<code>utils/request.js</code>是基于 <code>fetch</code> 的封装，便于统一处理 POST，GET 等请求参数，请求头，以及错误提示信息等</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// services/user.js</span></span><br><span class="line"><span class="keyword">import</span> request <span class="keyword">from</span> <span class="string">'../utils/request'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">query</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> request(<span class="string">'/api/users'</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">queryCurrent</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> request(<span class="string">'/api/currentUser'</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// models/user.js</span></span><br><span class="line"><span class="keyword">import</span> &#123; queryCurrent &#125; <span class="keyword">from</span> <span class="string">'../services/user'</span>;</span><br><span class="line">...</span><br><span class="line">effects: &#123;</span><br><span class="line">  *fetch(&#123; payload &#125;, &#123; call, put &#125;) &#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="keyword">const</span> response = <span class="keyword">yield</span> call(queryUsers);</span><br><span class="line">    ...</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><strong>处理异步请求</strong></p>
<blockquote>
<p>在处理复杂的异步请求的时候，很容易让逻辑混乱，陷入嵌套陷阱，所以 <code>Ant Design Pro</code> 的底层基础框架 <code>dva</code>使用 <code>effect</code> 的方式来管理同步化异步请求</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">effects: &#123;</span><br><span class="line">  *fetch(&#123; payload &#125;, &#123; call, put &#125;) &#123;</span><br><span class="line">    <span class="keyword">yield</span> put(&#123;</span><br><span class="line">      type: <span class="string">'changeLoading'</span>,</span><br><span class="line">      payload: <span class="literal">true</span>,</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="comment">// 异步请求 1</span></span><br><span class="line">    <span class="keyword">const</span> response = <span class="keyword">yield</span> call(queryFakeList, payload);</span><br><span class="line">    <span class="keyword">yield</span> put(&#123;</span><br><span class="line">      type: <span class="string">'save'</span>,</span><br><span class="line">      payload: response,</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="comment">// 异步请求 2</span></span><br><span class="line">    <span class="keyword">const</span> response2 = <span class="keyword">yield</span> call(queryFakeList2, payload);</span><br><span class="line">    <span class="keyword">yield</span> put(&#123;</span><br><span class="line">      type: <span class="string">'save2'</span>,</span><br><span class="line">      payload: response2,</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="keyword">yield</span> put(&#123;</span><br><span class="line">      type: <span class="string">'changeLoading'</span>,</span><br><span class="line">      payload: <span class="literal">false</span>,</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>
<h1 id="九、引入外部模块"><a href="#九、引入外部模块" class="headerlink" title="九、引入外部模块"></a>九、引入外部模块</h1><blockquote>
<p>除了<code>antd</code>组件以及脚手架内置的业务组件，有时我们还需要引入其他外部模块，这里以引入富文本组件 <code>react-quill</code> 为例进行介绍</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ npm install react-quill --save</span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> React <span class="keyword">from</span> <span class="string">'react'</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; Button, notification, Card &#125; <span class="keyword">from</span> <span class="string">'antd'</span>;</span><br><span class="line"><span class="keyword">import</span> ReactQuill <span class="keyword">from</span> <span class="string">'react-quill'</span>; </span><br><span class="line"><span class="keyword">import</span> <span class="string">'react-quill/dist/quill.snow.css'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="class"><span class="keyword">class</span> <span class="title">NewPage</span> <span class="keyword">extends</span> <span class="title">React</span>.<span class="title">Component</span> </span>&#123;</span><br><span class="line">  state = &#123;</span><br><span class="line">    value: <span class="string">'test'</span>,</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  handleChange = <span class="function">(<span class="params">value</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">this</span>.setState(&#123;</span><br><span class="line">      value,</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  prompt = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">    notification.open(&#123;</span><br><span class="line">      message: <span class="string">'We got value:'</span>,</span><br><span class="line">      description: <span class="xml"><span class="tag">&lt;<span class="name">span</span> <span class="attr">dangerouslySetInnerHTML</span>=<span class="string">&#123;&#123;</span> <span class="attr">__html:</span> <span class="attr">this.state.value</span> &#125;&#125;&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span>,</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  render() &#123;</span><br><span class="line">    <span class="keyword">return</span> (</span><br><span class="line">      &lt;Card title=<span class="string">"富文本编辑器"</span>&gt;</span><br><span class="line">        &lt;ReactQuill value=&#123;<span class="keyword">this</span>.state.value&#125; onChange=&#123;<span class="keyword">this</span>.handleChange&#125; /&gt;</span><br><span class="line">        &lt;Button style=&#123;&#123; <span class="attr">marginTop</span>: <span class="number">16</span> &#125;&#125; onClick=&#123;<span class="keyword">this</span>.prompt&#125;&gt;Prompt&lt;<span class="regexp">/Button&gt;</span></span><br><span class="line"><span class="regexp">      &lt;/</span>Card&gt;</span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="十、图表"><a href="#十、图表" class="headerlink" title="十、图表"></a>十、图表</h1><blockquote>
<p>Ant Design Pro 提供了由设计师精心设计抽象的图表类型，是在 <code>BizCharts</code> 图表库基础上的二次封装，同时提供了业务中常用的图表套件，可以单独使用，也可以组合起来实现复杂的展示效果</p>
</blockquote>
<blockquote>
<p>图表组件 <a href="https://pro.ant.design/components/Charts-cn/" target="_blank" rel="noopener">https://pro.ant.design/components/Charts-cn/</a></p>
</blockquote>
<p><strong>使用 Ant Design Pro 的图表</strong></p>
<p>Charts 图表套件是在 <code>components/Charts</code> 包中，引用到项目就像使用其它组件一样</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; ChartCard, MiniBar &#125; <span class="keyword">from</span> <span class="string">'@/components/Charts'</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; Tooltip, Icon &#125; <span class="keyword">from</span> <span class="string">'antd'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> visitData = [</span><br><span class="line">  &#123;</span><br><span class="line">    x: <span class="string">"2017-09-01"</span>,</span><br><span class="line">    y: <span class="number">100</span></span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    x: <span class="string">"2017-09-02"</span>,</span><br><span class="line">    y: <span class="number">120</span></span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    x: <span class="string">"2017-09-03"</span>,</span><br><span class="line">    y: <span class="number">88</span></span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    x: <span class="string">"2017-09-04"</span>,</span><br><span class="line">    y: <span class="number">65</span></span><br><span class="line">  &#125;</span><br><span class="line">];</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;ChartCard</span><br><span class="line">    title=<span class="string">"支付笔数"</span></span><br><span class="line">    action=&#123;</span><br><span class="line">      &lt;Tooltip title=<span class="string">"支付笔数反应交易质量"</span>&gt;</span><br><span class="line">        &lt;Icon type=<span class="string">"exclamation-circle-o"</span> /&gt;</span><br><span class="line">      &lt;<span class="regexp">/Tooltip&gt;</span></span><br><span class="line"><span class="regexp">    &#125;</span></span><br><span class="line"><span class="regexp">    total="6,500"</span></span><br><span class="line"><span class="regexp">    contentHeight=&#123;46&#125;</span></span><br><span class="line"><span class="regexp">  &gt;</span></span><br><span class="line"><span class="regexp">    &lt;MiniBar height=&#123;46&#125; data=&#123;visitData&#125; /</span>&gt;</span><br><span class="line">  &lt;<span class="regexp">/ChartCard&gt;,</span></span><br><span class="line"><span class="regexp">  mountNode</span></span><br><span class="line"><span class="regexp">);</span></span><br></pre></td></tr></table></figure>
<p><a href="https://github.com/alibaba/BizCharts" target="_blank" rel="noopener">https://github.com/alibaba/BizCharts</a></p>
<p><strong>使用 BizCharts 绘制图表</strong></p>
<blockquote>
<p>如果 <code>Ant Design Pro</code> 不能满足你的业务需求，可以直接使用 <code>BizCharts</code> 封装自己的图表组件。</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">npm install bizcharts --save</span><br></pre></td></tr></table></figure>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; Chart, Axis, Tooltip, Geom &#125; <span class="keyword">from</span> <span class="string">'bizcharts'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> data = [...];</span><br><span class="line"></span><br><span class="line">&lt;Chart height=&#123;<span class="number">400</span>&#125; data=&#123;data&#125; forceFit&gt;</span><br><span class="line">  &lt;Axis name=<span class="string">"month"</span> /&gt;</span><br><span class="line">  &lt;Axis name=<span class="string">"temperature"</span> label=&#123;&#123; <span class="attr">formatter</span>: <span class="function"><span class="params">val</span> =&gt;</span> <span class="string">`<span class="subst">$&#123;val&#125;</span>°C`</span> &#125;&#125; /&gt;</span><br><span class="line">  &lt;Tooltip crosshairs=&#123;&#123; <span class="attr">type</span> : <span class="string">"y"</span> &#125;&#125; /&gt;</span><br><span class="line">  &lt;Geom type=<span class="string">"line"</span> position=<span class="string">"month*temperature"</span> size=&#123;<span class="number">2</span>&#125; color=&#123;<span class="string">'city'</span>&#125; /&gt;</span><br><span class="line">  &lt;Geom type=<span class="string">'point'</span> position=<span class="string">"month*temperature"</span> size=&#123;<span class="number">4</span>&#125; color=&#123;<span class="string">'city'</span>&#125; /&gt;</span><br><span class="line">&lt;<span class="regexp">/Chart&gt;</span></span><br></pre></td></tr></table></figure>
<h1 id="十一、业务图标"><a href="#十一、业务图标" class="headerlink" title="十一、业务图标"></a>十一、业务图标</h1><blockquote>
<p>通常情况下，你可以通过 <code>Ant Design</code> 提供的 <code>&lt;Icon /&gt;</code> 图标组件来使用 Ant Design 官方图标。基本使用方式如下：</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">&lt;Icon type=&quot;heart&quot; style=&#123;&#123; fontSize: &apos;16px&apos;, color: &apos;hotpink&apos; &#125;&#125; /&gt;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>如果你没有在 <code>Ant Design</code> 官方图标中找到需要的图标，可以到 <code>iconfont.cn</code> 上采集并生成自己的业务图标库，再进行使用</p>
</blockquote>
<p><strong>生成图标库代码</strong></p>
<ul>
<li>首先，搜索并找到你需要的图标，将它采集到你的购物车里，在购物车里，你可以将选中的图标添加到项目中（没有的话，新建一个），后续生成的资源/代码都是以项目为维度的。</li>
<li>如果你已经有了设计稿，只是需要生成相关代码，可以上传你的图标后，再进行上面的操作</li>
</ul>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/jJQYzRyqVFBBamUOppXH.png" alt></p>
<blockquote>
<p>来到刚才选中的项目页，点击『生成代码』的链接，会在下方生成不同引入方式的代码，下面会分别介绍</p>
</blockquote>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/DbDSgiRukSANKWyhULir.png" alt></p>
<p><strong>引入</strong></p>
<ul>
<li>有三种引入方式供你选择：<code>SVG Symbol</code>、<code>Unicode</code> 及 <code>Font class</code>。我们推荐在现代浏览器下使用 <code>SVG Symbol</code>方式引入。</li>
</ul>
<blockquote>
<p>SVG 符号引入是现代浏览器未来主流的图标引入方式。其方法是预先加载符号，在合适的地方引入并渲染为矢量图形。有如下特点：</p>
</blockquote>
<ul>
<li>支持多色图标，不再受到单色图标的限制</li>
<li>通过一些技巧，支持像字体那样，通过 <code>font-size</code>、<code>color</code> 来调整样式</li>
<li>支持IE 9+ 及现代浏览器</li>
</ul>
<blockquote>
<p>切换到 <code>Symbol</code> 页签，复制项目生成的地址代码：</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.js</span><br></pre></td></tr></table></figure>
<p>加入图标样式代码，如果没有特殊的要求，你可以直接复用 Ant Design 图标的样式</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">.icon &#123;</span><br><span class="line">  width: 1em;</span><br><span class="line">  height: 1em;</span><br><span class="line">  fill: currentColor;</span><br><span class="line">  vertical-align: -.125em;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>挑选相应图标并获取类名，应用于页面</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">&lt;svg class=&quot;icon&quot; aria-hidden=&quot;true&quot;&gt;</span><br><span class="line">    &lt;use xlink:href=&quot;#icon-ali-pay&quot;&gt;&lt;/use&gt;</span><br><span class="line">&lt;/svg&gt;</span><br></pre></td></tr></table></figure>
<p>你也可以通过使用 Ant Design 图标组件提供的 <code>Icon.createFromIconfontCN({...})</code> 方法来更加方便地使用图标，使用方式如下：</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">import &#123; Icon &#125; from &apos;antd&apos;;</span><br><span class="line"></span><br><span class="line">const IconFont = Icon.createFromIconfontCN(&#123;</span><br><span class="line">  scriptUrl: &apos;//at.alicdn.com/t/font_405362_lyhvoky9rc7ynwmi.js&apos;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">export default IconFont;</span><br></pre></td></tr></table></figure>
<p>之后可以像使用 <code>&lt;Icon /&gt;</code> 组件一样方便地使用，支持配置样式</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">&lt;IconFont type=&quot;icon-ali-pay&quot; style=&#123;&#123; fontSize: &apos;16px&apos;, color: &apos;lightblue&apos; &#125;&#125; /&gt;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>了解更多用法 <a href="https://pro.ant.design/docs/biz-icon-cn#%E4%BA%8C%E3%80%81%E5%BC%95%E5%85%A5" target="_blank" rel="noopener">https://pro.ant.design/docs/biz-icon-cn#%E4%BA%8C%E3%80%81%E5%BC%95%E5%85%A5</a></p>
</blockquote>
<h1 id="十二、Mock-和联调"><a href="#十二、Mock-和联调" class="headerlink" title="十二、Mock 和联调"></a>十二、Mock 和联调</h1><blockquote>
<p>Mock 数据是前端开发过程中必不可少的一环，是分离前后端开发的关键链路。通过预先跟服务器端约定好的接口，模拟请求数据甚至逻辑，能够让前端开发独立自主，不会被服务端的开发所阻塞</p>
</blockquote>
<ul>
<li>在 <code>Ant Design Pro</code> 中，因为我们的底层框架是 <code>umi</code>，而它自带了代理请求功能，通过代理请求就能够轻松处理数据模拟的功能</li>
</ul>
<p><strong>使用 umi 的 mock 功能</strong></p>
<blockquote>
<p>umi 里约定 mock 文件夹下的文件即 mock 文件，文件导出接口定义，支持基于 require 动态分析的实时刷新，支持 ES6 语法，以及友好的出错提示</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="comment">// 支持值为 Object 和 Array</span></span><br><span class="line">  <span class="string">'GET /api/users'</span>: &#123; <span class="attr">users</span>: [<span class="number">1</span>, <span class="number">2</span>] &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// GET POST 可省略</span></span><br><span class="line">  <span class="string">'/api/users/1'</span>: &#123; <span class="attr">id</span>: <span class="number">1</span> &#125;,</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 支持自定义函数，API 参考 express@4</span></span><br><span class="line">  <span class="string">'POST /api/users/create'</span>: <span class="function">(<span class="params">req, res</span>) =&gt;</span> &#123; res.end(<span class="string">'OK'</span>); &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>当客户端（浏览器）发送请求，如：<code>GET /api/users</code>，那么本地启动的 umi dev 会跟此配置文件匹配请求路径以及方法，如果匹配到了，就会将请求通过配置处理，就可以像样例一样，你可以直接返回数据，也可以通过函数处理以及重定向到另一个服务器</p>
</blockquote>
<p>了解更多 <a href="https://pro.ant.design/docs/mock-api-cn#%E4%BD%BF%E7%94%A8-umi-%E7%9A%84-mock-%E5%8A%9F%E8%83%BD" target="_blank" rel="noopener">https://pro.ant.design/docs/mock-api-cn#%E4%BD%BF%E7%94%A8-umi-%E7%9A%84-mock-%E5%8A%9F%E8%83%BD</a></p>
<h1 id="十三、主题定制"><a href="#十三、主题定制" class="headerlink" title="十三、主题定制"></a>十三、主题定制</h1><blockquote>
<p>我们基于 Ant Design React 进行开发，完全支持官方提供的 less 变量定制功能. 你可以在脚手架目录中找到 <code>config/config.js</code> 代码类似这样</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">...</span><br><span class="line">theme: &#123;</span><br><span class="line">  &apos;font-size-base&apos;: &apos;14px&apos;,</span><br><span class="line">  &apos;badge-font-size&apos;: &apos;12px&apos;,</span><br><span class="line">  &apos;btn-font-size-lg&apos;: &apos;@font-size-base&apos;,</span><br><span class="line">  &apos;menu-dark-bg&apos;: &apos;#00182E&apos;,</span><br><span class="line">  &apos;menu-dark-submenu-bg&apos;: &apos;#000B14&apos;,</span><br><span class="line">  &apos;layout-sider-background&apos;: &apos;#00182E&apos;,</span><br><span class="line">  &apos;layout-body-background&apos;: &apos;#f0f2f5&apos;,</span><br><span class="line">&#125;;</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
<h1 id="十四、权限管理"><a href="#十四、权限管理" class="headerlink" title="十四、权限管理"></a>十四、权限管理</h1><blockquote>
<p>只需要在配置菜单的时候配置上准入身份，在登录成功以后获取到登陆者身份以后更新登录人身份参数即可</p>
</blockquote>
<h2 id="权限组件-Authorized"><a href="#权限组件-Authorized" class="headerlink" title="权限组件 Authorized"></a>权限组件 Authorized</h2><blockquote>
<p>这是脚手架权限管理的基础，基本思路是通过比对当前权限与准入权限，决定展示正常渲染内容还是异常内容</p>
</blockquote>
<p><strong>控制菜单和路由显示</strong></p>
<blockquote>
<p>如需对某些页面进行权限控制，只须在路由配置文件 <code>router.config.js</code> 中设置 <code>authority</code> 属性即可，代表该路由的准入权限，pro 的路由系统中会默认包裹 <code>Authorized</code> 进行判断处理。</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  path: <span class="string">'/form'</span>,</span><br><span class="line">  icon: <span class="string">'form'</span>,</span><br><span class="line">  name: <span class="string">'form'</span>,</span><br><span class="line">  routes:[&#123;</span><br><span class="line">    path: <span class="string">'/form/basic-form'</span>,</span><br><span class="line">    name: <span class="string">'basicform'</span>,</span><br><span class="line">    component: <span class="string">'./Forms/BasicForm'</span>,</span><br><span class="line">  &#125;, &#123;</span><br><span class="line">    path: <span class="string">'/form/step-form'</span>,</span><br><span class="line">    name: <span class="string">'stepform'</span>,</span><br><span class="line">    component: <span class="string">'./Forms/StepForm'</span>,</span><br><span class="line">    authority: [<span class="string">'guest'</span>], <span class="comment">// 配置准入权限，可以配置多个角色</span></span><br><span class="line">  &#125;, &#123;</span><br><span class="line">    path: <span class="string">'/form/advanced-form'</span>,</span><br><span class="line">    name: <span class="string">'advancedform'</span>,</span><br><span class="line">    component: <span class="string">'./Forms/AdvancedForm'</span>,</span><br><span class="line">    authority: [<span class="string">'admin'</span>], <span class="comment">// 配置准入权限，可以配置多个角色</span></span><br><span class="line">  &#125;],</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="控制页面元素显示"><a href="#控制页面元素显示" class="headerlink" title="控制页面元素显示"></a>控制页面元素显示</h2><blockquote>
<p>使用 <code>Authorized</code> 或<code>Authorized.Secured</code> 可以很方便地控制元素/组件的渲染。<a href="https://pro.ant.design/components/Authorized#Authorized.Secured" target="_blank" rel="noopener">https://pro.ant.design/components/Authorized#Authorized.Secured</a></p>
</blockquote>
<h2 id="demo关于权限简介"><a href="#demo关于权限简介" class="headerlink" title="demo关于权限简介"></a>demo关于权限简介</h2><ul>
<li>用邮箱自己注册账户（注册后可以登录但是没有任何权限）<code>guest</code></li>
<li>联系管理员分配权限（分配后可以查看有权限的页面）</li>
<li>每次登录后获取最新的权限身份（如：<code>admin</code>，<code>user</code>，<code>guest</code>）</li>
</ul>
<blockquote>
<p>在<code>src/router.js</code>中会发现如下代码</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">AuthorizedRoute</span></span></span><br><span class="line"><span class="tag">    <span class="attr">path</span>=<span class="string">"/"</span></span></span><br><span class="line"><span class="tag">    <span class="attr">render</span>=<span class="string">&#123;props</span> =&gt;</span> <span class="tag">&lt;<span class="name">BasicLayout</span> &#123;<span class="attr">...props</span>&#125; /&gt;</span>&#125;</span><br><span class="line">    authority=&#123;['admin', 'user', 'guest']&#125;</span><br><span class="line">    redirectPath="/user/login"</span><br><span class="line">/&gt;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>其中<code>authority</code>对象就是准入身份的数组，表示只有这些身份的人可以登录，我们在配置的时候一定不要忘记在这更新我们新增的身份</p>
</blockquote>
<ul>
<li>然后就是<code>menu.js</code>,如下，展示了我们在配置菜单的时候怎么配身份</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> menuData = [&#123;</span><br><span class="line">  name: <span class="string">'题库管理'</span>,</span><br><span class="line">  path: <span class="string">'question'</span>,</span><br><span class="line">  icon: <span class="string">'warning'</span>,</span><br><span class="line">  authority: [<span class="string">'admin'</span>, <span class="string">'user'</span>],</span><br><span class="line">  children: [&#123;</span><br><span class="line">    name: <span class="string">'题库列表'</span>,</span><br><span class="line">    path: <span class="string">'list'</span>,</span><br><span class="line">  &#125;, &#123;</span><br><span class="line">    name: <span class="string">'编辑题目'</span>,</span><br><span class="line">    path: <span class="string">'create-question'</span>,</span><br><span class="line">    hideInMenu: <span class="literal">true</span>,</span><br><span class="line">  &#125;, &#123;</span><br><span class="line">    name: <span class="string">'科目管理'</span></span><br><span class="line">  &#125;]</span><br><span class="line">&#125;, &#123;</span><br><span class="line">  name: <span class="string">'账号管理'</span>,</span><br><span class="line">  icon: <span class="string">'warning'</span>,</span><br><span class="line">  path: <span class="string">'account'</span>,</span><br><span class="line">  children: [&#123;</span><br><span class="line">    name: <span class="string">'账号列表'</span>,</span><br><span class="line">    path: <span class="string">'list'</span>,</span><br><span class="line">    authority: <span class="string">'admin'</span>,</span><br><span class="line">  &#125;, &#123;</span><br><span class="line">    name: <span class="string">'建设中'</span>,</span><br><span class="line">    path: <span class="string">''</span>,</span><br><span class="line">    authority: [<span class="string">'admin'</span>, <span class="string">'user'</span>],</span><br><span class="line">  &#125;]</span><br><span class="line">&#125;]</span><br></pre></td></tr></table></figure>
<blockquote>
<p>登录成功以后怎么获取权限了</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">effects：&#123;</span><br><span class="line">* login(&#123;payload&#125;, &#123;call, put&#125;) &#123;</span><br><span class="line">      <span class="keyword">const</span> response = <span class="keyword">yield</span> call(login, payload);</span><br><span class="line">      <span class="keyword">yield</span> put(&#123;</span><br><span class="line">        type: <span class="string">'changeLoginStatus'</span>,</span><br><span class="line">        payload: response,</span><br><span class="line">      &#125;);</span><br><span class="line">      <span class="comment">// 登录成功以后更新权限，跳转页面</span></span><br><span class="line">      <span class="keyword">if</span> (response &amp;&amp; response.code === <span class="string">'0000'</span>) &#123;</span><br><span class="line">        reloadAuthorized();</span><br><span class="line">        <span class="keyword">yield</span> put(routerRedux.push(<span class="string">'/'</span>));</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;，</span><br><span class="line">reducers: &#123;</span><br><span class="line">    changeLoginStatus(state, &#123;payload&#125;) &#123;</span><br><span class="line">      <span class="keyword">let</span> _status = <span class="string">"ok"</span>;</span><br><span class="line">      <span class="keyword">let</span> _user = <span class="string">"admin"</span>;</span><br><span class="line">      setToken(<span class="string">"token"</span>);</span><br><span class="line">      setAuthority(_user);<span class="comment">//设置权限</span></span><br><span class="line">      <span class="keyword">return</span> &#123;</span><br><span class="line">        ...state,</span><br><span class="line">        status: _status,</span><br><span class="line">        type: <span class="string">'account'</span>,</span><br><span class="line">      &#125;;</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;</span><br></pre></td></tr></table></figure>
<ul>
<li>我们看看<code>setAuthority</code>、<code>reloadAuthorized</code>这两个方法都做了什么事儿</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//设置身份</span></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">setAuthority</span>(<span class="params">authority</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> localStorage.setItem(<span class="string">'antd-pro-authority'</span>, authority);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//获取身份</span></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">getAuthority</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> localStorage.getItem(<span class="string">'antd-pro-authority'</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p>如此而且，只是把新的身份值存在<code>localStorage</code>里边，注意<code>getAuthority</code>，下边会用到</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> RenderAuthorized <span class="keyword">from</span> <span class="string">'../components/Authorized'</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; getAuthority &#125; <span class="keyword">from</span> <span class="string">'./authority'</span>;</span><br><span class="line"><span class="keyword">let</span> Authorized = RenderAuthorized(getAuthority());</span><br><span class="line"><span class="keyword">const</span> reloadAuthorized = <span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">  Authorized = RenderAuthorized(getAuthority());</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">export</span> &#123; reloadAuthorized &#125;;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> Authorized;</span><br><span class="line">RenderAuthorized: <span class="function">(<span class="params">currentAuthority: string | (</span>) =&gt;</span> string) =&gt; Authorized</span><br></pre></td></tr></table></figure>
<blockquote>
<p>权限组件默认 <code>export RenderAuthorized</code> 函数，它接收当前权限作为参数，返回一个权限对象，该对象提供以下几种使用方式</p>
</blockquote>
<p><strong>Authorized</strong></p>
<blockquote>
<p>最基础的权限控制</p>
</blockquote>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>children</code></td>
<td>正常渲染的元素，权限判断通过时展示</td>
</tr>
<tr>
<td><code>authority</code></td>
<td>准入权限/权限判断</td>
</tr>
<tr>
<td><code>noMatch</code></td>
<td>权限异常渲染元素，权限判断不通过时展示</td>
</tr>
</tbody>
</table>
<p><strong>Authorized.AuthorizedRoute</strong></p>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>authority</code></td>
<td>准入权限/权限判断</td>
</tr>
<tr>
<td><code>redirectPath</code></td>
<td>权限异常时重定向的页面路由</td>
</tr>
</tbody>
</table>
<p><strong>Authorized.Secured</strong></p>
<blockquote>
<p>注解方式，<a href="mailto:`@Authorized.Secured" target="_blank" rel="noopener">`@Authorized.Secured</a>(authority, error)`</p>
</blockquote>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>authority</code></td>
<td>准入权限/权限判断</td>
</tr>
<tr>
<td><code>error</code></td>
<td>权限异常时渲染元素</td>
</tr>
</tbody>
</table>
<p><strong>Authorized.check</strong></p>
<blockquote>
<p>函数形式的 <code>Authorized</code>，用于某些不能被 <code>HOC</code> 包裹的组件。 <code>Authorized.check(authority, target, Exception)</code></p>
</blockquote>
<ul>
<li>注意：传入一个 <code>Promise</code> 时，无论正确还是错误返回的都是一个 <code>ReactClass</code></li>
</ul>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>authority</code></td>
<td>准入权限/权限判断</td>
</tr>
<tr>
<td><code>target</code></td>
<td>权限判断通过时渲染的元素</td>
</tr>
<tr>
<td><code>Exception</code></td>
<td>权限异常时渲染元素</td>
</tr>
</tbody>
</table>
<h1 id="十五、构建和发布"><a href="#十五、构建和发布" class="headerlink" title="十五、构建和发布"></a>十五、构建和发布</h1><p><strong>构建</strong></p>
<blockquote>
<p>当项目开发完毕，只需要运行一行命令就可以打包你的应用：</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ npm run build</span><br></pre></td></tr></table></figure>
<blockquote>
<p>由于 Ant Design Pro 使用的工具 Umi 已经将复杂的流程封装完毕，构建打包文件只需要一个命令 umi build，构建打包成功之后，会在根目录生成 dist 文件夹，里面就是构建打包好的文件，通常是 <em>.js、</em>.css、index.html 等静态文件</p>
</blockquote>
<p><strong>分析构建文件体积</strong></p>
<blockquote>
<p>如果你的构建文件很大，你可以通过 analyze 命令构建并分析依赖模块的体积分布，从而优化你的代码。</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ npm run analyze</span><br></pre></td></tr></table></figure>
<p><strong>发布</strong></p>
<blockquote>
<p>对于发布来讲，只需要将最终生成的静态文件，也就是通常情况下 dist 文件夹的静态文件发布到你的 cdn 或者静态服务器即可，需要注意的是其中的 <code>index.html</code> 通常会是你后台服务的入口页面，在确定了 js 和 css 的静态之后可能需要改变页面的引入路径</p>
</blockquote>
<p><strong>前端路由与服务端的结合</strong></p>
<blockquote>
<p>Ant Design Pro 使用的 Umi 支持两种路由方式：<code>browserHistory</code> 和 <code>hashHistory</code>。</p>
</blockquote>
<ul>
<li>可以在 <code>config/config.js</code> 中进行配置选择用哪个方式：</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  history: <span class="string">'hash'</span>, <span class="comment">// 默认是 browser</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="十六、一些问题"><a href="#十六、一些问题" class="headerlink" title="十六、一些问题"></a>十六、一些问题</h1><h2 id="在ant-design-pro中解决跨域办法"><a href="#在ant-design-pro中解决跨域办法" class="headerlink" title="在ant-design-pro中解决跨域办法"></a>在ant-design-pro中解决跨域办法</h2><blockquote>
<p>需要在配置文件中(<code>.webpackrc</code>)加入如下代码</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="string">"proxy"</span>: &#123;</span><br><span class="line">  <span class="string">"/api"</span>: &#123;</span><br><span class="line">    <span class="string">"target"</span>: <span class="string">"http://xxx:xx/"</span>,</span><br><span class="line">    <span class="string">"changeOrigin"</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="string">"pathRewrite"</span>: &#123; <span class="string">"^/api"</span> : <span class="string">""</span> &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>
<blockquote>
<p>需要注意的是此处不是将<code>/api/</code>代理到正式请求<code>/api/</code>中，（例如请求<code>/api/users</code>则会代理到<code>http://xxx:xx/users</code>）<br>如果需要多次代理且需要代理到不同的服务器则可以在配置文件中进行如下配置</p>
</blockquote>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="string">"proxy"</span>: &#123;</span><br><span class="line">      <span class="string">"/test"</span>: &#123;</span><br><span class="line">        <span class="string">"target"</span>: <span class="string">"http://xxx:xx/"</span>,</span><br><span class="line">        <span class="string">"changeOrigin"</span>: <span class="literal">true</span>,</span><br><span class="line">        <span class="string">"pathRewrite"</span>: &#123; <span class="string">"^/test"</span> : <span class="string">""</span> &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="string">"/cross"</span>: &#123;</span><br><span class="line">        <span class="string">"target"</span>: <span class="string">"http://jsonplaceholder.typicode.com"</span>,</span><br><span class="line">        <span class="string">"changeOrigin"</span>: <span class="literal">true</span>,</span><br><span class="line">        <span class="string">"pathRewrite"</span>: &#123;<span class="string">"^/cross"</span>: <span class="string">""</span>&#125;</span><br><span class="line">      &#125; <span class="comment">// 此处有一点需要注意，不能在最后一个代理对象后面加逗号，否则会报错！！！</span></span><br><span class="line">  &#125;,</span><br></pre></td></tr></table></figure>
<h2 id="在model中怎么同时发起多次请求"><a href="#在model中怎么同时发起多次请求" class="headerlink" title="在model中怎么同时发起多次请求"></a>在model中怎么同时发起多次请求</h2><blockquote>
<p>因为<code>yield</code>将异步请求转为同步请求了，所以请求会按照同步顺序依次执行，使请求时间延长</p>
</blockquote>
<p><strong>错误写法</strong></p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// effects将按顺序执行</span></span><br><span class="line"><span class="keyword">const</span> response = <span class="keyword">yield</span> call(fetch, <span class="string">'/users'</span>);</span><br><span class="line"><span class="keyword">const</span> res = <span class="keyword">yield</span> call(fetch, <span class="string">'/roles'</span>);</span><br></pre></td></tr></table></figure>
<p><strong>正确写法</strong></p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// effects将会同步执行</span></span><br><span class="line"><span class="keyword">const</span> [response, res] = <span class="keyword">yield</span> [</span><br><span class="line">  call(fetch, <span class="string">'/users'</span>),</span><br><span class="line">  call(fetch, <span class="string">'/roles'</span>),</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

      </div>
    
  </div>

</article>

<button class="assist-btn2 circle" id="assist_btn2" title="点亮屏幕" style="left: 27px; top: 152px;">
  <i class="iconfont" style="display:inline-block;color:red;width:20px;height:20px;">&#xe61d;</i>
</button>
<button class="assist-btn1 circle" id="assist_btn1" title="关闭屏幕亮度" style="left: 27px; top: 152px;">
  <i class="iconfont toc-title" style="display:inline-block;color:red;width:20px;height:20px;">&#xe61d;</i>
</button>


<script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>	

<script src="https://my.openwrite.cn/js/readmore.js" type="text/javascript"></script>
<script>
  const btw = new BTWPlugin();
  btw.init({
    id: "container",
    blogId: "22699-1592137983091-414",
    name: "前端进阶之旅",
    qrcode: "https://poetries1.gitee.io/img-repo/2020/06/qrcode.jpg",
    keyword: "3a3b3c",
  });
</script>

<script type="text/javascript">

// white theme
var body = {color: "#555", background: "#000"};
var a_tag = {color: "#222"};
var header = { background: "#222"};
var logo_line_i = {background: "#222"};
// var post_code = {background: "#eee", color: "#222"};

function switch_theme() {
 $("body").css(body);
 $("a:not('.links-of-author-item a, .site-state-item a, .site-state-posts a, .feed-link a, .motion-element a, .post-tags a, .show-commit-cls a, #donate_board a')").css(a_tag);
 $(".header, .footer").css(header);
 $(".logo-line-before i, .logo-line-after i").css(logo_line_i);
 //$(".post code").css(post_code);
 $("#idhyt-surprise-ball #idhyt-surprise-ball-animation .drag").css(a_tag);
 $(".post-title-link, .posts-expand .post-meta, .post-comments-count, .disqus-comment-count, .post-category a, .post-nav-next a, .post-nav-item a").css(a_tag);
 
 // $("code").css({color: '#c5c8c6', background: '#1d1f21'});
 //$("#assist_btn1").hide(1500);
}

$(function () {
$("#assist_btn2").css("display","none");
 $("#assist_btn1").click(function() {
     switch_theme();
$("div#toc.toc-article").css({
 "background":"#eaeaea",
 "opacity":1
});
$(".toc-article ol").show();
$("#toc.toc-article .toc-title").css("color","#a98602");
$("#assist_btn1").css("display","none");
$("#assist_btn2").css("display","block");
 });
$("#assist_btn2").click(function() {
$("#assist_btn2").css("display","none");
$("#assist_btn1").css("display","block");
$("body").css("background","url(http://www.miaov.com/static/ie/images/news/bg.png)")
     $(".header, .footer").css("background","url(http://www.miaov.com/static/ie/images/news/bg.png)")
$(".toc-article ol").toggle(1000);
 });
});


//背景随机

var Y, O, E, L, B, C, T, z, N, S, A, I;
!function() {
var e = function() {
for (O.clearRect(0, 0, L, B), T = [{
x: 0,
y: .7 * B + C
}, {
x: 0,
y: .7 * B - C
}]; T[1].x < L + C;) t(T[0], T[1])
}, t = function(e, t) {
O.beginPath(), O.moveTo(e.x, e.y), O.lineTo(t.x, t.y);
var n = t.x + (2 * I() - .25) * C,
 r = a(t.y);
O.lineTo(n, r), O.closePath(), N -= S / -50, O.fillStyle = "#" + (127 * A(N) + 128 << 16 | 127 * A(N + S / 3) + 128 << 8 | 127 * A(N + S / 3 * 2) + 128).toString(16), O.fill(), T[0] = T[1], T[1] = {
 x: n,
 y: r
}
}, a = function n(e) {
var t = e + (2 * I() - 1.1) * C;
return t > B || t < 0 ? n(e) : t
};
Y = document.getElementById("evanyou"), O = Y.getContext("2d"), E = window.devicePixelRatio || 1, L = window.innerWidth, B = window.innerHeight, C = 90, z = Math, N = 0, S = 2 * z.PI, A = z.cos, I = z.random, Y.width = L * E, Y.height = B * E, O.scale(E, E), O.globalAlpha = .6, document.onclick = e, document.ontouchstart = e, e()
}()

   
$("#toc-eye").click(function(){
$("#toc.toc-article").toggle(1000);
});

</script>


   
  <div class="text-center donation">
    <div class="inner-donation">
      <span class="btn-donation">支持一下</span>
      <div class="donation-body">
        <div class="tip text-center">扫一扫，支持poetries</div>
        <ul>
        
          <li class="item">
            
              <span>微信扫一扫</span>
            
            <img src="/images/weixin.jpg" alt="">
          </li>
        
          <li class="item">
            
              <span>支付宝扫一扫</span>
            
            <img src="/images/zhifubao.jpg" alt="">
          </li>
        
        </ul>
      </div>
    </div>
  </div>


   
  <div class="box-prev-next clearfix">
    <a class="show pull-left" href="/2018/09/07/umi-dva/">
        <i class="icon icon-angle-left"></i>
    </a>
    <a class="show pull-right" href="/2018/09/17/graphviz/">
        <i class="icon icon-angle-right"></i>
    </a>
  </div>




</div>


  <a id="backTop" class="back-top">
    <i class="icon-angle-up"></i>
  </a>




  <div class="modal" id="modal">
  <span id="cover" class="cover hide"></span>
  <div id="modal-dialog" class="modal-dialog hide-dialog">
    <div class="modal-header">
      <span id="close" class="btn-close">关闭</span>
    </div>
    <hr>
    <div class="modal-body">
      <ul class="list-toolbox">
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/archives/"
              rel="noopener noreferrer"
              target="_self"
              >
              博客
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/categories/"
              rel="noopener noreferrer"
              target="_self"
              >
              分类
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/tags/"
              rel="noopener noreferrer"
              target="_self"
              >
              标签
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/search/"
              rel="noopener noreferrer"
              target="_self"
              >
              搜索
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/link/"
              rel="noopener noreferrer"
              target="_self"
              >
              友链
            </a>
          </li>
        
          <li class="item-toolbox">
            <a
              class="CIRCLE"
              href="/about/"
              rel="noopener noreferrer"
              target="_self"
              >
              关于
            </a>
          </li>
        
      </ul>

    </div>
  </div>
</div>



  
      <div class="fexo-comments comments-post">
    

    

    
    

    

    
    

    

<!-- Gitalk评论插件通用代码 -->
<div id="gitalk-container"></div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.css">
<script src="https://cdn.jsdelivr.net/npm/gitalk@1/dist/gitalk.min.js"></script>
<script>
const gitalk = new Gitalk({
  clientID: '5567a2c4abb858009d96',
  clientSecret: 'b9039ec056cf5c2346b3cdb63308a28c163f91e5',
  repo: 'poetries.github.io',
  owner: 'poetries',
  // 在这里设置一下截取前50个字符串, 这是因为 github 对 label 的长度有了要求, 如果超过
  // 50个字符串则会报错.
  // id: location.pathname.split('/').pop().substring(0, 49),
  id: location.pathname,
  admin: ['poetries'],
  // facebook-like distraction free mode
  distractionFreeMode: false
})
gitalk.render('gitalk-container')
</script>
<!-- Gitalk代码结束 -->



  </div>

  

  <script type="text/javascript">
  function loadScript(url, callback) {
    var script = document.createElement('script')
    script.type = 'text/javascript';

    if (script.readyState) { //IE
      script.onreadystatechange = function() {
        if (script.readyState == 'loaded' ||
          script.readyState == 'complete') {
          script.onreadystatechange = null;
          callback();
        }
      };
    } else { //Others
      script.onload = function() {
        callback();
      };
    }

    script.src = url;
    document.getElementsByTagName('head')[0].appendChild(script);
  }

  window.onload = function() {
    loadScript('/js/bundle.js?235683', function() {
      // load success
    });
  }
</script>


  <!-- 页面点击小红心 -->
  <script type="text/javascript" src="/js/clicklove.js"></script>
 
  
</body>
</html>
